package cre.tomcat7.ch09.core;

import org.apache.catalina.*;

import javax.servlet.ServletException;
import java.io.IOException;

/**
 * @Author penglai
 * @Date 2017/1/27.
 */
public class SimplePipeline implements Pipeline, Lifecycle {

    private Valve basicValve;
    private Valve[] valves = new Valve[0];
    private Container container;

    public SimplePipeline(Container container) {
        this.container = container;
    }

    public void addValve(Valve valve) {
        if (valve instanceof Contained) {
            ((Contained) valve).setContainer(container);
        }

        synchronized (valves) {
            Valve[] ret = new Valve[valves.length + 1];
            System.arraycopy(valves, 0, ret, 0, valves.length);
            ret[valves.length] = valve;
            valves = ret;
        }
    }

    public Valve getBasic() {
        return basicValve;
    }

    public Valve[] getValves() {
        return valves;
    }

    public void invoke(Request request, Response response) throws IOException, ServletException {
        new SimplePipelineValveContent().invokeNext(request, response);
    }

    public void removeValve(Valve valve) {
    }

    public void setBasic(Valve valve) {
        basicValve = valve;
        ((Contained) basicValve).setContainer(container);
    }

    public void addLifecycleListener(LifecycleListener listener) {

    }

    public LifecycleListener[] findLifecycleListeners() {
        return new LifecycleListener[0];
    }

    public void removeLifecycleListener(LifecycleListener listener) {

    }

    public void start() throws LifecycleException {
        System.out.println("start simple pipeline");
    }

    public void stop() throws LifecycleException {
        System.out.println("stop simple pipeline");
    }

    protected class SimplePipelineValveContent implements ValveContext {

        protected int stage = 0;

        public String getInfo() {
            return null;
        }

        public void invokeNext(Request request, Response response) throws IOException, ServletException {
            int subscript = stage;
            stage += 1;

            if (subscript < valves.length) {
                valves[subscript].invoke(request, response, this);
            } else if (subscript == valves.length && basicValve != null) {
                basicValve.invoke(request, response, this);
            } else {
                throw new ServletException("No Valves");
            }
        }
    }
}
